package com.station.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.google.common.base.Charsets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HttpUtils {
	private static Logger logger = LoggerFactory.getLogger(HttpUtils.class);

	private static final String LIST_KEY = "list";
	
	private static final String OBJECT_KEY = "obj";




	/**
	 * 描述: 发起http请求并获取结果
	 *
	 * @param requestUrl
	 * @param requestMethod
	 * @param outputStr
	 * @return
	 */
	public static String httpRequest(String requestUrl, String requestMethod, String outputStr,String contentType) {
		StringBuffer buffer = null;
		String result ="";
		try {
			URL url = new URL(requestUrl);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setRequestMethod(requestMethod);
			if(contentType!=null){
				conn.setRequestProperty("Content-Type",  contentType);
			}
			conn.setRequestProperty("Accept-Charset", "utf-8");
			conn.connect();
			//往服务器端写内容 也就是发起http请求需要带的参数
			if (null != outputStr) {
				OutputStream os = conn.getOutputStream();
				os.write(outputStr.getBytes("utf-8"));
				os.close();
			}
			int responceCode = conn.getResponseCode();
			if (responceCode == HttpURLConnection.HTTP_OK) {
				//读取服务器端返回的内容
				InputStream is = conn.getInputStream();
				InputStreamReader isr = new InputStreamReader(is, "utf-8");
				BufferedReader br = new BufferedReader(isr);
				buffer = new StringBuffer();
				String line = null;
				while ((line = br.readLine()) != null) {
					buffer.append(line);
				}
				result = buffer.toString();
			}
		} catch (Exception e) {
			logger.error(requestMethod + "请求出错,URL:{},参数:{},堆栈信息:{}", requestUrl, outputStr, e);
		}
		return result;
	}

	/**
	 * 将map转换成url
	 *
	 * @param map
	 * @return url参数字符串
	 */
	public static String getUrlParamsByMap(Map<String, Object> map) {
		if (map == null) {
			return "";
		}
		StringBuffer sb = new StringBuffer("?");
		for (Map.Entry<String, Object> entry : map.entrySet()) {
			sb.append(entry.getKey() + "=" + entry.getValue());
			sb.append("&");
		}
		String s = sb.toString();
		if (s.endsWith("&")) {
			s = org.apache.commons.lang.StringUtils.substringBeforeLast(s, "&");
		}
		return s;
	}

	/**
	 * HTTP Get 请求
	 *
	 * @param params 参数
	 * @param url    地址
	 * @return JSONObject
	 */
	public static JSONObject get(Map<String, Object> params, String url) {
		logger.info("开始GET请求...");
		String paramsUrl = HttpUtils.getUrlParamsByMap(params);
		logger.info("请求地址{}{}",url,paramsUrl);

		RestTemplate restTemplate = new RestTemplate();
		restTemplate.getMessageConverters().set(1,new StringHttpMessageConverter(Charsets.UTF_8));
		String result = (String) restTemplate.getForObject(url + paramsUrl, String.class, new Object[0]);
		logger.info("完成GET,结果:{}",result);

		return  JSON.parseObject(result);
	}

	/**
	 * HTTP Get 请求
	 *
	 * @param params 参数
	 * @param url    地址
	 * @return JSONObject
	 */
	public static String getString(Map<String, Object> params, String url) {
		logger.info("开始GET请求...");
		String paramsUrl = HttpUtils.getUrlParamsByMap(params);
		logger.info("请求地址{}{}",url,paramsUrl);

		RestTemplate restTemplate = new RestTemplate();
		String result = (String) restTemplate.getForObject(url + paramsUrl, String.class, new Object[0]);
		logger.info("完成GET,结果:{}",result);

		return  result;
	}


	/**
	 * HTTP Post 请求
	 *
	 * @param params 参数
	 * @param url    地址
	 * @return JSONObject
	 */
	public static JSONObject post(Object params, String url) {
		logger.info("开始POST请求...");
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.parseMediaType("application/json; charset=UTF-8"));
		headers.add("Accept", MediaType.APPLICATION_JSON.toString());
		String requstParams = JSONObject.toJSONString(params);

		logger.info("请求参数{},请求地址{}",requstParams,url);
		HttpEntity<String> httpEntity = new HttpEntity<>(requstParams, headers);

		RestTemplate restTemplate = new RestTemplate();
		ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(url, httpEntity, String.class);
		logger.info("完成POST,结果:{}",stringResponseEntity.getBody());

		return JSONObject.parseObject(stringResponseEntity.getBody(),Feature.OrderedField);
	}

	/**
	 * JSON对象将指定key为'list'转换为list集合
	 * @param resJson  对象(JSON)
	 * @param clazz    转换类型
	 * @return         返回转换后的集合
	 */
	public static <T> List<T> getList(JSONObject resJson, Class<T> clazz) {
		return getList(resJson, LIST_KEY, clazz);
	}

	/**
	 * JSON对象将指定key为'obj'转换为对象
	 * @param resJson  对象(JSON)
	 * @param clazz    转换类型
	 * @return         返回转换后的对象
	 */
	public static <T> T getObject(JSONObject resJson, Class<T> clazz) {
		return getObject(resJson, OBJECT_KEY, clazz);
	}

	/**
	 * JSON对象将指定key转换为对象
	 * @param resJson  对象(JSON)
	 * @param key  键值key
	 * @param clazz    转换类型
	 * @return         返回转换后的对象
	 */
	public static <T> T getObject(JSONObject resJson, String key, Class<T> clazz) {
		if (resJson.containsKey(key)) {
			Object obj = resJson.get(key);
			if (obj instanceof JSONObject) {
				return JSON.toJavaObject((JSONObject) obj, clazz);
			}
		}
		try {
			return clazz.newInstance();
		} catch (InstantiationException | IllegalAccessException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * JSON对象将指定key转换为list集合
	 * @param resJson  对象(JSON)
	 * @param listKey  键值key
	 * @param clazz    转换类型
	 * @return         返回转换后的集合
	 */
	public static <T> List<T> getList(JSONObject resJson, String listKey, Class<T> clazz) {
		if (resJson.containsKey(listKey)) {
			Object obj = resJson.get(listKey);
			if (obj instanceof JSONArray) {
				return JSONObject.parseArray(((JSONArray) obj).toJSONString(), clazz);
			}
		}
		return new ArrayList<T>(0);
	}

	/**
	 * URL结果中获取指定key为'list'的数据转为指定list集合
	 * @param params 请求参数
	 * @param url    请求地址
	 * @param clazz  指定转换对象类型
	 * @return 		   返回集合
	 */
	public static <T> List<T> postForList(Object params, String url, Class<T> clazz) {
		return postForList(params, url, LIST_KEY, clazz);
	}

	/**
	 * URL结果中获取指定key的数据转为指定list集合
	 * @param params 请求参数
	 * @param url    请求地址
	 * @param key    指定获取数据键值
	 * @param clazz  指定转换对象类型
	 * @return 		   返回集合
	 */
	public static <T> List<T> postForList(Object params, String url, String key, Class<T> clazz) {
		return getList(post(params, url), clazz);
	}


	/**
	 * URL结果中获取指定key为'obj'的数据转为指定对象
	 * @param params 请求参数
	 * @param url    请求地址
	 * @param clazz  指定转换对象类型
	 * @return 		   返回对象
	 */
	public static <T> T postForObject(Object params, String url, Class<T> clazz) {
		return postForObject(params, url, OBJECT_KEY, clazz);
	}

	/**
	 * URL结果中获取指定key的数据转为指定对象
	 * @param params 请求参数
	 * @param url    请求地址
	 * @param key    指定获取数据键值
	 * @param clazz  指定转换对象类型
	 * @return 		   返回对象
	 */
	public static <T> T postForObject(Object params, String url, String key, Class<T> clazz) {
		JSONObject jsonObject = post(params, url);
		return getObject(jsonObject, key, clazz);
	}

	public static PageUtils getReturnPageUtils(Map<String, Object> params, String url) {
		JSONObject resultJson = get(params, url);
		PageUtils pageUtils = JSON.parseObject(((JSONObject) resultJson.get("page")).toJSONString(), PageUtils.class);
		return pageUtils;
	}
}
